/**
 * @file PagerSlideTab.java
 * @create 下午5:04:54
 * @author CX
 * @description 自定义的PagerSlideTab pagerView滑动与tab标签的组合,不包括viewpager
 * @使用方法:在布局文件中包含该View,可以设置颜色大小高度,然后在java代码中控制...颜色,大小,高度等 ,setViewPager();
 */
package cn.edu.hstc.wm.widget;

import java.util.Locale;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;

import cn.edu.hstc.wm.R;

/**
 * @ClassName: PagerSlideTab 
 * @Description: TODO
 * 
 * @ModificationHistory 
 */
public class PagerSlideTab extends HorizontalScrollView {

	public static final String TAG = "PagerSlideTab";

	/** 在Tab上使用图标来显示的接口 */
	public interface IconTabProvider {
		public int getPageIconResId(int position);
	}

	// @formatter:off
	private static final int[] ATTRS = new int[] { android.R.attr.textSize,
			android.R.attr.textColor };
	// @formatter:on

	/** Tab默认外观Layout,显示标题包裹内容大小 */
	private LinearLayout.LayoutParams defaultTabLayoutParams;
	/** Tab扩展外观 Layout,显示标题为平均分 */
	private LinearLayout.LayoutParams expandedTabLayoutParams;

	private final PageListener pageListener = new PageListener();
	public OnPageChangeListener delegatePageListener;

	/** Tab标签容器 */
	private LinearLayout tabsContainer;
	private ViewPager pager;

	/** Tab个数 */
	private int tabCount;
	/** tab显示的当前位置 */
	private int currentPosition = 0;
	/** tab显示当前位置的偏移量 */
	private float currentPositionOffset = 0f;
	/** 滚动偏移 */
	private int scrollOffset = 52;
	private int lastScrollX = 0;

	private Paint rectPaint; // 画矩形的paint
	private Paint dividerPaint;// 画tab分割线的paint

	/** tab指示器颜色 */
	private int indicatorColor = 0xFF666666;
	/** tab下面一横线的颜色 */
	private int underlineColor = 0x1A000000;
	/** tab分割线的颜色 */
	private int dividerColor = 0x1A000000;

	/** 是否均等分 */
	private boolean shouldExpand = false;
	/** 英文是否全部为大写 */
	private boolean textAllCaps = true;

	/** tab 指示器高度 */
	private int indicatorHeight = 8;
	/** tab 下划线高度 */
	private int underlineHeight = 2;
	/** tab 分割线内边距 */
	private int dividerPadding = 12;
	/** tab 内边距 */
	private int tabPadding = 24;
	/** tab 分割线宽度 */
	private int dividerWidth = 1;
	/** 显示字体属性 */
	private int tabTextSize = 14;
	// private int tabTextColor = 0xFF666666;
	private ColorStateList tabTextColor = null;
	private Typeface tabTypeface = null;
	private int tabTypefaceStyle = Typeface.BOLD;

	/** tab背景颜色 ,不同状态的显示效果 */
	private int tabBackgroundResId = R.drawable.bg_pagerslidetab;

	private Locale locale;

	public PagerSlideTab(Context context) {
		this(context, null);
	}

	public PagerSlideTab(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public PagerSlideTab(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		setFillViewport(true);
		setWillNotDraw(false);

		tabsContainer = new LinearLayout(context);
		tabsContainer.setOrientation(LinearLayout.HORIZONTAL);
		// tabsContainer.setGravity(Gravity.CENTER_HORIZONTAL); // 水平居中
		tabsContainer.setLayoutParams(new LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
		addView(tabsContainer);// 添加tab容器到这个水平滚动view上

		DisplayMetrics dm = getResources().getDisplayMetrics();

		// 转成对应的参数
		scrollOffset = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm);
		indicatorHeight = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, indicatorHeight, dm);
		underlineHeight = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, underlineHeight, dm);
		dividerPadding = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, dividerPadding, dm);
		tabPadding = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, tabPadding, dm);
		dividerWidth = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, dividerWidth, dm);
		tabTextSize = (int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_SP, tabTextSize, dm);

		// 获取系统属性 (android:textSize and android:textColor)
		TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
		tabTextSize = a.getDimensionPixelSize(0, tabTextSize);
		tabTextColor = a.getColorStateList(1);

		a.recycle();

		// 获取自定义的属性 (设置值 ,默认值)
		a = context.obtainStyledAttributes(attrs, R.styleable.PagerSlideTab);

		// tabTextColor = a.getColor(R.styleable.PagerSlideTab_pstTextColor,
		// tabTextColor);
		tabTextColor = a
				.getColorStateList(R.styleable.PagerSlideTab_pstTextColor);
		indicatorColor = a.getColor(
				R.styleable.PagerSlideTab_pstIndicatorColor, indicatorColor);
		underlineColor = a.getColor(
				R.styleable.PagerSlideTab_pstUnderlineColor, underlineColor);
		dividerColor = a.getColor(R.styleable.PagerSlideTab_pstDividerColor,
				dividerColor);
		tabTextSize = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstTextSize, tabTextSize);
		indicatorHeight = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstIndicatorHeight, indicatorHeight);
		underlineHeight = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstUnderlineHeight, underlineHeight);
		dividerPadding = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstDividerPadding, dividerPadding);
		dividerWidth = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstDividerWidth, dividerWidth);
		tabPadding = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstTabPaddingLeftRight, tabPadding);
		tabBackgroundResId = a.getResourceId(
				R.styleable.PagerSlideTab_pstTabBackground, tabBackgroundResId);
		shouldExpand = a.getBoolean(R.styleable.PagerSlideTab_pstShouldExpand,
				shouldExpand);
		scrollOffset = a.getDimensionPixelSize(
				R.styleable.PagerSlideTab_pstScrollOffset, scrollOffset);
		textAllCaps = a.getBoolean(R.styleable.PagerSlideTab_pstTextAllCaps,
				textAllCaps);

		a.recycle();

		// 画tab和下划线的paint
		rectPaint = new Paint();
		rectPaint.setAntiAlias(true);// 抗锯齿
		rectPaint.setStyle(Style.FILL);// 填充

		// 画分隔条的paint
		dividerPaint = new Paint();
		dividerPaint.setAntiAlias(true);
		dividerPaint.setStrokeWidth(dividerWidth); // 设置下划线宽度

		// 包裹内容布局
		defaultTabLayoutParams = new LinearLayout.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
		// 均等分布局
		expandedTabLayoutParams = new LinearLayout.LayoutParams(0,
				LayoutParams.MATCH_PARENT, 1.0f);

		if (locale == null) {
			locale = getResources().getConfiguration().locale;
		}
	}

	/**
	 * 设置于该View对应使用的ViewPager ;使用了这个方法的Viewpager可以不用设置OnPagerChangedListener监听
	 * 设置用到的标题大小,颜色等在这个方法之前调用才有效
	 * 
	 * @param pager
	 */
	public void setViewPager(ViewPager pager) {
		this.pager = pager;

		if (pager.getAdapter() == null) {
			throw new IllegalStateException(
					"ViewPager does not have adapter instance.");
		}
		//
		pager.setOnPageChangeListener(pageListener);
		//
		notifyDataSetChanged();
	}

	/**
	 * 使用ViewPager的监听器
	 * 
	 * @param listener
	 */
	public void setOnPageChangeListener(OnPageChangeListener listener) {
		this.delegatePageListener = listener;
	}

	/**
	 * 通知数据改变了
	 */
	public void notifyDataSetChanged() {
		// 移除所有的view
		tabsContainer.removeAllViews();

		// 获取叶卡个数
		tabCount = pager.getAdapter().getCount();

		for (int i = 0; i < tabCount; i++) {
			// 使用了图标适配器的图片tab
			if (pager.getAdapter() instanceof IconTabProvider) {
				addIconTab(i,
						((IconTabProvider) pager.getAdapter())
								.getPageIconResId(i));
			} else {
				// 纯文字的tab
				addTextTab(i, pager.getAdapter().getPageTitle(i).toString());
			}

		}

		updateTabStyles();

		Log.v(TAG, "getViewTreeObserver().isAlive() = "
				+ getViewTreeObserver().isAlive());
		// 添加全局布局的监听器
		getViewTreeObserver().addOnGlobalLayoutListener(
				new OnGlobalLayoutListener() {

					@SuppressWarnings("deprecation")
					@SuppressLint("NewApi")
					@Override
					public void onGlobalLayout() {

						if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
							getViewTreeObserver().removeGlobalOnLayoutListener(
									this);
						} else {
							getViewTreeObserver().removeOnGlobalLayoutListener(
									this);
						}

						currentPosition = pager.getCurrentItem();
						scrollToChild(currentPosition, 0);
						updateSelection(currentPosition);
					}
				});

	}

	/**
	 * 添加文字的tab,把字符串内容包装为TextView
	 * 
	 * @param position
	 *            位置
	 * @param title
	 *            显示标题内容
	 */
	private void addTextTab(final int position, String title) {

		TextView tab = new TextView(getContext());
		tab.setText(title);
		// tab.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); // 加粗
		tab.setGravity(Gravity.CENTER);
		tab.setSingleLine();
		addTab(position, tab);
	}

	/**
	 * 添加图片类型的tab,用ImageButton包装
	 * 
	 * @param position
	 *            位置
	 * @param resId
	 *            图片资源id
	 */
	private void addIconTab(final int position, int resId) {
		ImageButton tab = new ImageButton(getContext());
		tab.setImageResource(resId);
		addTab(position, tab);
	}

	/**
	 * 添加到tab ,包括图片,文字
	 * 
	 * @param position
	 * @param tab
	 */
	private void addTab(final int position, final View tab) {
		tab.setFocusable(true);
		tab.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				pager.setCurrentItem(position);
			}
		});

		// 设置每个tab的属性
		tab.setPadding(tabPadding, 0, tabPadding, 0);
		// 这里才是添加到tab容器中
		tabsContainer
				.addView(tab, position, shouldExpand ? expandedTabLayoutParams
						: defaultTabLayoutParams);
	}

	/**
	 * 更新tab的外观样式
	 */
	private void updateTabStyles() {

		for (int i = 0; i < tabCount; i++) {
			View v = tabsContainer.getChildAt(i);
			v.setBackgroundResource(tabBackgroundResId);

			if (v instanceof TextView) {
				TextView textView = (TextView) v;
				textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabTextSize);
				textView.setTypeface(tabTypeface, tabTypefaceStyle);
				// textView.setTextColor(tabTextColor);
				if (tabTextColor != null) {
					textView.setTextColor(tabTextColor);
				}

				// 把字符串转化为大写的
				if (textAllCaps) {
					// 高版本自带方法
					if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
						textView.setAllCaps(true);
					} else {
						// 低版本解决方案
						textView.setText(textView.getText().toString()
								.toUpperCase(locale));
					}
				}
			}
		}

	}

	/**
	 * 更新当前选中的tab的状态
	 * 
	 * @param position
	 */
	public void updateSelection(int position) {
		for (int i = 0; i < tabCount; ++i) {
			View tv = tabsContainer.getChildAt(i);
			tv.setSelected(i == position);//
		}
	}

	/**
	 * 滚动到指定位置
	 * 
	 * @param position
	 *            目的位置
	 * @param offset
	 *            偏移量
	 */
	private void scrollToChild(int position, int offset) {

		if (tabCount == 0) {
			return;
		}
		// 距离容器左边距离
		int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset;

		if (position > 0 || offset > 0) {
			newScrollX -= scrollOffset;
		}

		if (newScrollX != lastScrollX) {
			lastScrollX = newScrollX;
			scrollTo(newScrollX, 0);
		}

	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (isInEditMode() || tabCount == 0) {
			return;
		}

		// PagerSlideTab的高度
		final int height = getHeight();

		// 当前的tab
		View currentTab = tabsContainer.getChildAt(currentPosition);
		float lineLeft = currentTab.getLeft();// 距离左边
		float lineRight = currentTab.getRight();// 距离右边

		// 移动是重新计算移动位置
		if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {

			View nextTab = tabsContainer.getChildAt(currentPosition + 1);
			final float nextTabLeft = nextTab.getLeft();
			final float nextTabRight = nextTab.getRight();
			//
			lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
					* lineLeft);
			lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset)
					* lineRight);
		}
		// Log.v(TAG, "onDraw" + this.toString());
		// 画指示器的颜色
		rectPaint.setColor(indicatorColor);
		// 画tab指示器
		canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height,
				rectPaint);

		// 画下划线
		rectPaint.setColor(underlineColor);
		canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(),
				height, rectPaint);

		// 画tab间的分割线
		dividerPaint.setColor(dividerColor);
		for (int i = 0; i < tabCount - 1; i++) {
			View tab = tabsContainer.getChildAt(i);
			canvas.drawLine(tab.getRight(), dividerPadding, tab.getRight(),
					height - dividerPadding, dividerPaint);
		}
	}

	/**
	 * 设置指示器颜色
	 * 
	 * @param indicatorColor
	 */
	public void setIndicatorColor(int indicatorColor) {
		this.indicatorColor = indicatorColor;
		invalidate();
	}

	/**
	 * 设置指示器颜色资源
	 * 
	 * @param resId
	 */
	public void setIndicatorColorResource(int resId) {
		this.indicatorColor = getResources().getColor(resId);
		invalidate();
	}

	public int getIndicatorColor() {
		return this.indicatorColor;
	}

	/**
	 * 设置高度
	 * 
	 * @param indicatorLineHeightPx
	 */
	public void setIndicatorHeight(int indicatorLineHeightPx) {
		this.indicatorHeight = indicatorLineHeightPx;
		invalidate();
	}

	public int getIndicatorHeight() {
		return indicatorHeight;
	}

	/**
	 * 设置下划线颜色
	 * 
	 * @param underlineColor
	 */
	public void setUnderlineColor(int underlineColor) {
		this.underlineColor = underlineColor;
		invalidate();
	}

	/**
	 * 设置下划线颜色资源值
	 * 
	 * @param resId
	 */
	public void setUnderlineColorResource(int resId) {
		this.underlineColor = getResources().getColor(resId);
		invalidate();
	}

	public int getUnderlineColor() {
		return underlineColor;
	}

	/**
	 * 设置分割线颜色
	 * 
	 * @param dividerColor
	 */
	public void setDividerColor(int dividerColor) {
		this.dividerColor = dividerColor;
		invalidate();
	}

	/**
	 * 设置分割线颜色资源值
	 * 
	 * @param resId
	 */
	public void setDividerColorResource(int resId) {
		this.dividerColor = getResources().getColor(resId);
		invalidate();
	}

	public int getDividerColor() {
		return dividerColor;
	}

	/**
	 * 设置下划线高度
	 * 
	 * @param underlineHeightPx
	 */
	public void setUnderlineHeight(int underlineHeightPx) {
		this.underlineHeight = underlineHeightPx;
		invalidate();
	}

	public int getUnderlineHeight() {
		return underlineHeight;
	}

	/**
	 * 设置分割线内边距
	 * 
	 * @param dividerPaddingPx
	 */
	public void setDividerPadding(int dividerPaddingPx) {
		this.dividerPadding = dividerPaddingPx;
		invalidate();
	}

	public int getDividerPadding() {
		return dividerPadding;
	}

	/**
	 * 设置偏移量值
	 * 
	 * @param scrollOffsetPx
	 */
	public void setScrollOffset(int scrollOffsetPx) {
		this.scrollOffset = scrollOffsetPx;
		invalidate();
	}

	public int getScrollOffset() {
		return scrollOffset;
	}

	/**
	 * 是否扩展
	 * 
	 * @param shouldExpand
	 */
	public void setShouldExpand(boolean shouldExpand) {
		this.shouldExpand = shouldExpand;
		requestLayout();
	}

	public boolean getShouldExpand() {
		return shouldExpand;
	}

	/**
	 * 是否全部大写
	 * 
	 * @return
	 */
	public boolean isTextAllCaps() {
		return textAllCaps;
	}

	/**
	 * 设置是否为大写形式,默认是全部大写模式
	 * 
	 * @param textAllCaps
	 */
	public void setAllCaps(boolean textAllCaps) {
		this.textAllCaps = textAllCaps;
	}

	/**
	 * 设置标题字体大小
	 * 
	 * @param textSizePx
	 */
	public void setTextSize(int textSizePx) {
		this.tabTextSize = textSizePx;
		updateTabStyles();
	}

	public int getTextSize() {
		return tabTextSize;
	}

	/**
	 * 设置标题字体颜色
	 * 
	 * @param textColor
	 */
	public void setTextColor(ColorStateList textColor) {
		this.tabTextColor = textColor;
		updateTabStyles();
	}

	/**
	 * 设置标题字体颜色资源值
	 * 
	 * @param textColor
	 */
	public void setTextColorResource(int resId) {
		this.tabTextColor = getResources().getColorStateList(resId);
		updateTabStyles();
	}

	public ColorStateList getTextColor() {
		return tabTextColor;
	}

	/**
	 * 设置字体样式
	 * 
	 * @param typeface
	 * @param style
	 */
	public void setTypeface(Typeface typeface, int style) {
		this.tabTypeface = typeface;
		this.tabTypefaceStyle = style;
		updateTabStyles();
	}

	/**
	 * 设置tab的背景颜色资源值
	 * 
	 * @param resId
	 */
	public void setTabBackground(int resId) {
		this.tabBackgroundResId = resId;
		updateTabStyles();
	}

	public int getTabBackground() {
		return tabBackgroundResId;
	}

	/**
	 * 设置tab左右边距
	 * 
	 * @param paddingPx
	 */
	public void setTabPaddingLeftRight(int paddingPx) {
		this.tabPadding = paddingPx;
		updateTabStyles();
	}

	public int getTabPaddingLeftRight() {
		return tabPadding;
	}

	@Override
	public void onRestoreInstanceState(Parcelable state) {
		SavedState savedState = (SavedState) state;
		super.onRestoreInstanceState(savedState.getSuperState());
		currentPosition = savedState.currentPosition;
		requestLayout();
	}

	@Override
	public Parcelable onSaveInstanceState() {
		Parcelable superState = super.onSaveInstanceState();
		SavedState savedState = new SavedState(superState);
		savedState.currentPosition = currentPosition;
		return savedState;
	}

	/**
	 * ViewPager的叶卡监听
	 */
	private class PageListener implements OnPageChangeListener {

		@Override
		public void onPageScrolled(int position, float positionOffset,
				int positionOffsetPixels) {

			currentPosition = position;
			currentPositionOffset = positionOffset;

			scrollToChild(position, (int) (positionOffset * tabsContainer
					.getChildAt(position).getWidth()));

			invalidate();

			if (delegatePageListener != null) {
				delegatePageListener.onPageScrolled(position, positionOffset,
						positionOffsetPixels);
			}
		}

		@Override
		public void onPageScrollStateChanged(int state) {
			if (state == ViewPager.SCROLL_STATE_IDLE) {
				scrollToChild(pager.getCurrentItem(), 0);
			}

			if (delegatePageListener != null) {
				delegatePageListener.onPageScrollStateChanged(state);
			}
		}

		@Override
		public void onPageSelected(int position) {
			updateSelection(position);
			if (delegatePageListener != null) {
				delegatePageListener.onPageSelected(position);
			}
		}

	}

	static class SavedState extends BaseSavedState {
		int currentPosition;

		public SavedState(Parcelable superState) {
			super(superState);
		}

		private SavedState(Parcel in) {
			super(in);
			currentPosition = in.readInt();
		}

		@Override
		public void writeToParcel(Parcel dest, int flags) {
			super.writeToParcel(dest, flags);
			dest.writeInt(currentPosition);
		}

		public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() {
			@Override
			public SavedState createFromParcel(Parcel in) {
				return new SavedState(in);
			}

			@Override
			public SavedState[] newArray(int size) {
				return new SavedState[size];
			}
		};
	}

	@Override
	public String toString() {
		return "PagerSlideTab [defaultTabLayoutParams="
				+ defaultTabLayoutParams + ", expandedTabLayoutParams="
				+ expandedTabLayoutParams + ", pageListener=" + pageListener
				+ ", delegatePageListener=" + delegatePageListener
				+ ", tabsContainer=" + tabsContainer + ", pager=" + pager
				+ ", tabCount=" + tabCount + ", currentPosition="
				+ currentPosition + ", currentPositionOffset="
				+ currentPositionOffset + ", rectPaint=" + rectPaint
				+ ", dividerPaint=" + dividerPaint + ", indicatorColor="
				+ indicatorColor + ", underlineColor=" + underlineColor
				+ ", dividerColor=" + dividerColor + ", shouldExpand="
				+ shouldExpand + ", textAllCaps=" + textAllCaps
				+ ", scrollOffset=" + scrollOffset + ", indicatorHeight="
				+ indicatorHeight + ", underlineHeight=" + underlineHeight
				+ ", dividerPadding=" + dividerPadding + ", tabPadding="
				+ tabPadding + ", dividerWidth=" + dividerWidth
				+ ", tabTextSize=" + tabTextSize + ", tabTextColor="
				+ tabTextColor + ", tabTypeface=" + tabTypeface
				+ ", tabTypefaceStyle=" + tabTypefaceStyle + ", lastScrollX="
				+ lastScrollX + ", tabBackgroundResId=" + tabBackgroundResId
				+ ", locale=" + locale + "]";
	}

}
